import streamlit as st
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
import re
import time
import jwt
import requests
import os
from app3 import CareerAdvisor
import hashlib

# 初始化 CareerAdvisor 实例
advisor = CareerAdvisor(api_key="输入你自己的api_key")

# ==============================================
# 用户认证系统
# ==============================================

def initialize_auth():
    """初始化用户认证系统"""
    if 'users' not in st.session_state:
        st.session_state.users = {}
    if 'logged_in' not in st.session_state:
        st.session_state.logged_in = False
    if 'current_user' not in st.session_state:
        st.session_state.current_user = None
    if 'auth_mode' not in st.session_state:
        st.session_state.auth_mode = 'login'  # 默认显示登录界面

def hash_password(password):
    """使用SHA-256哈希密码"""
    return hashlib.sha256(password.encode()).hexdigest()

def register_user(username, password, email=None):
    """注册新用户"""
    if username in st.session_state.users:
        return False, "用户名已存在"
    
    hashed_pw = hash_password(password)
    st.session_state.users[username] = {
        'password': hashed_pw,
        'email': email,
        'preferences': {}
    }
    return True, "注册成功"

def login_user(username, password):
    """用户登录"""
    if username not in st.session_state.users:
        return False, "用户名不存在"
    
    hashed_pw = hash_password(password)
    if st.session_state.users[username]['password'] != hashed_pw:
        return False, "密码错误"
    
    st.session_state.logged_in = True
    st.session_state.current_user = username
    return True, "登录成功"

def logout_user():
    """用户登出"""
    st.session_state.logged_in = False
    st.session_state.current_user = None
    st.session_state.auth_mode = 'login'

def show_auth_form():
    """显示认证表单（登录/注册）"""
    st.markdown("""
    <style>
    .auth-container {
        max-width: 400px;
        margin: 0 auto;
        padding: 20px;
        border-radius: 10px;
        box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
        background-color: #f8f9fa;
    }
    .auth-title {
        text-align: center;
        color: #2c3e50;
        margin-bottom: 20px;
    }
    .auth-button {
        width: 100%;
        margin-top: 10px;
    }
    .auth-switch {
        text-align: center;
        margin-top: 15px;
        color: #7f8c8d;
    }
    .switch-button {
        background: none;
        border: none;
        color: #3498db;
        text-decoration: underline;
        cursor: pointer;
        padding: 0;
    }
    </style>
    """, unsafe_allow_html=True)

    with st.container():
        st.markdown('<h1 class="auth-title">PathFinder职途明灯</h1>', unsafe_allow_html=True)
        
        if st.session_state.auth_mode == 'login':
            st.markdown('<h2 class="auth-title">用户登录</h2>', unsafe_allow_html=True)
            with st.form("login_form"):
                username = st.text_input("用户名", key="login_username")
                password = st.text_input("密码", type="password", key="login_password")
                submitted = st.form_submit_button("登录", type="primary")
                
                if submitted:
                    success, message = login_user(username, password)
                    if success:
                        st.success(message)
                        st.rerun()  # 修改这里
                    else:
                        st.error(message)
            
            # 使用按钮代替链接
            col1, col2 = st.columns([0.7, 0.3])
            with col1:
                st.markdown('<div class="auth-switch">没有账号？</div>', unsafe_allow_html=True)
            with col2:
                if st.button("立即注册", key="switch_to_register_btn"):
                    st.session_state.auth_mode = 'register'
                    st.rerun()  # 修改这里
        
        else:  # 注册模式
            st.markdown('<h2 class="auth-title">用户注册</h2>', unsafe_allow_html=True)
            with st.form("register_form"):
                username = st.text_input("用户名", key="register_username")
                email = st.text_input("电子邮箱（可选）", key="register_email")
                password = st.text_input("密码", type="password", key="register_password")
                confirm_password = st.text_input("确认密码", type="password", key="register_confirm_password")
                submitted = st.form_submit_button("注册", type="primary")
                
                if submitted:
                    if password != confirm_password:
                        st.error("两次输入的密码不一致")
                    else:
                        success, message = register_user(username, password, email)
                        if success:
                            st.success(message)
                            st.session_state.auth_mode = 'login'
                            st.rerun()  # 修改这里
                        else:
                            st.error(message)
            
            # 使用按钮代替链接
            col1, col2 = st.columns([0.7, 0.3])
            with col1:
                st.markdown('<div class="auth-switch">已有账号？</div>', unsafe_allow_html=True)
            with col2:
                if st.button("立即登录", key="switch_to_login_btn"):
                    st.session_state.auth_mode = 'login'
                    st.rerun()  # 修改这里
        
        st.markdown('</div>', unsafe_allow_html=True)

# ==============================================
# 数据加载和工具函数
# ==============================================

def load_data():
    try:
        data = pd.read_csv('拉勾网2023招聘数据.csv')
        print("数据基本信息：")
        data.info()
        print("数据前几行：")
        print(data.head())
        return data
    except FileNotFoundError:
        print("未找到数据集文件，请检查文件路径和文件名。")
        return None

# 在程序启动时加载数据
data = load_data()

if data is not None:
    print("数据加载成功")
    print("数据列名:", data.columns)
    if 'positionName' in data.columns:
        data['positionName'] = data['positionName'].str.strip()
    if 'city' in data.columns:
        data['city'] = data['city'].str.strip()
    if 'salary' in data.columns:
        data['salary'] = data['salary'].str.replace(r'[^\d-]', '', regex=True)

# 薪资提取函数
def extract_salary_avg(salary_str):
    matches = re.findall(r'\d+', salary_str)
    if matches:
        numbers = [int(num) for num in matches]
        if len(numbers) == 2:
            return (numbers[0] + numbers[1]) / 2
        elif len(numbers) == 1:
            return numbers[0]
    return None

# ==============================================
# 数据分析函数 (来自app2.py)
# ==============================================

def count_job(job_name):
    if data is not None:
        filtered_data = data[data['positionName'].str.contains(job_name, na=False, case=False)]
        print(f"筛选出包含 {job_name} 的岗位的数据数量: {len(filtered_data)}")
        return len(filtered_data)
    return 0

def average_salary(job_name):
    if data is not None:
        salary_data = data[data['positionName'].str.contains(job_name, na=False, case=False)]['salary']
        print(f"筛选出 {job_name} 岗位的薪资数据数量: {len(salary_data)}")
        valid_salaries = []
        for salary_str in salary_data:
            avg = extract_salary_avg(salary_str)
            if avg is not None:
                valid_salaries.append(avg)
        print(f"有效薪资数据数量: {len(valid_salaries)}")
        if valid_salaries:
            result = sum(valid_salaries) / len(valid_salaries)
            result = round(result, 2)
            print(f"{job_name} 岗位的平均薪资: {result}")
            return result
    print(f"{job_name} 岗位未找到有效薪资数据，返回 0")
    return 0

def salary_trend_by_experience(city):
    if data is not None:
        city_data = data[data['city'] == city].copy()
        avg_salaries = []
        for _, row in city_data.iterrows():
            salary_str = row['salary']
            matches = re.findall(r'\d+', salary_str)
            if matches:
                numbers = [int(num) for num in matches]
                if len(numbers) == 2:
                    avg = (numbers[0] + numbers[1]) / 2
                    avg_salaries.append(avg)
                elif len(numbers) == 1:
                    avg_salaries.append(numbers[0])
        if avg_salaries:
            city_data.loc[:, 'avg_salary'] = avg_salaries
            result = city_data.groupby('workYear')['avg_salary'].mean()
            result = result.round(2)
            return result
    return pd.Series()

def count_job_by_city(job_name, city):
    if data is not None:
        if 'positionName' not in data.columns or 'city' not in data.columns:
            print("数据集中缺少必要的列名: positionName 或 city")
            return 0
        job_name = job_name.strip()
        city = city.strip()
        filtered_data = data[(data['positionName'].str.contains(job_name, case=False)) & 
                            (data['city'].str.lower() == city.lower())]
        print(f"筛选出 {city} 城市中 {job_name} 岗位的数据数量: {len(filtered_data)}")
        return len(filtered_data)
    return 0

def job_distribution_by_education(job_name):
    if data is not None:
        filtered_data = data[data['positionName'] == job_name]
        print(f"筛选出 {job_name} 岗位的数据数量: {len(filtered_data)}")
        return filtered_data['education'].value_counts()
    return pd.Series()

def language_demand_ratio(job_name):
    if data is not None:
        languages = ['Python', 'Java', 'C++', 'C#', 'JavaScript', 'Go', 'Ruby', 'PHP', 'Swift', 'Kotlin']
        job_data = data[data['positionName'].str.contains(job_name, na=False)]
        total_jobs = len(job_data)
        language_counts = {lang: 0 for lang in languages}

        if 'positionDetail' in job_data.columns:
            for requirement in job_data['positionDetail']:
                if isinstance(requirement, str):
                    for lang in languages:
                        if lang in requirement:
                            language_counts[lang] += 1

        language_demand = pd.Series(language_counts)
        return language_demand / total_jobs if total_jobs > 0 else pd.Series()
    return pd.Series()

def company_distribution_by_benefit(benefit):
    if data is not None:
        filtered_data = data[data['companyLabelList'].apply(lambda x: benefit in x)]
        return filtered_data.groupby(['industryField', 'city']).size()
    return pd.Series()

def job_count_comparison(education, work_year):
    if data is not None:
        print(f"筛选前的数据数量: {len(data)}")
        print(f"education 列唯一值: {data['education'].unique()}")
        print(f"workYear 列唯一值: {data['workYear'].unique()}")
        
        filtered_data = data[(data['education'] == education) & (data['workYear'] == work_year)]
        print(f"筛选后的数据数量: {len(filtered_data)}")
        
        result = filtered_data.groupby('positionName')['positionName'].count()
        return result
    return pd.Series()

# ==============================================
# AI 相关函数 (来自app4.py)
# ==============================================

def generate_token(apikey: str, exp_seconds: int):
    try:
        id, secret = apikey.split(".")
    except Exception as e:
        raise Exception("invalid apikey", e)

    payload = {
        "api_key": id,
        "exp": int(round(time.time() * 1000)) + exp_seconds * 1000,
        "timestamp": int(round(time.time() * 1000)),
    }
    return jwt.encode(
        payload,
        secret,
        algorithm="HS256",
        headers={"alg": "HS256", "sign_type": "SIGN"},
    )

def ask_glm(key, model, max_tokens, temperature, content):
    url = "https://open.bigmodel.cn/api/paas/v4/chat/completions"
    headers = {
      'Content-Type': 'application/json',
      'Authorization': generate_token(key, 1000)
    }

    data = {
        "model": model,
        "max_tokens": max_tokens,
        "temperature": temperature,
        "messages": content
    }

    response = requests.post(url, headers=headers, json=data)
    return response.json()

patterns = {
    "count_job": r"统计(?!.*城市中)(.*)岗位的数量",  
    "average_salary": r"(.*)的平均薪资是多少",
    "count_job_by_city": r"统计(.*)城市中(.*)岗位的数量",
    "job_distribution_by_education": r"(.*)对不同学历层次学生的职位需求分布如何",
    "salary_trend_by_experience": r"(.*)不同工作年限要求下，职位的平均薪资增长趋势是怎样的",
    "language_demand_ratio": r"(.*)在(.*)岗位的需求占比如何",
    "company_distribution_by_benefit": r"提供(.*)福利的公司，在(.*)行业和(.*)的分布情况如何",
    "job_count_comparison": r"(.*)学历和(.*)工作年限要求下，各职位的招聘数量对比如何",
    "skill_association": r"我比较擅长(.*)，请给我推荐一些关联技术",
    "position_skills": r"从事(.*)岗位需要学什么？",
    "skill_positions": r"我会(.*)，什么岗位比较适合我？"
}

def search_local_data(prompt):
    for func_name, pattern in patterns.items():
        match = re.search(pattern, prompt)
        if match:
            print(f"匹配到函数 {func_name}，捕获到的参数: {match.groups()}")
            if func_name == "count_job":
                return str(count_job(match.group(1)))
            elif func_name == "average_salary":
                return str(average_salary(match.group(1)))
            elif func_name == "count_job_by_city":
                return str(count_job_by_city(match.group(2), match.group(1)))
            elif func_name == "job_distribution_by_education":
                result = job_distribution_by_education(match.group(1))
                formatted_result = '\n'.join([f"{index} {value}" for index, value in result.items()])
                return formatted_result
            elif func_name == "salary_trend_by_experience":
                city = match.group(1)
                result = salary_trend_by_experience(city)
                formatted_result = '\n'.join([f"{index} {round(value, 2)}k" for index, value in result.items()])
                return formatted_result
            elif func_name == "language_demand_ratio":
                return str(language_demand_ratio(match.group(2)))
            elif func_name == "company_distribution_by_benefit":
                return str(company_distribution_by_benefit(match.group(1)))
            elif func_name == "job_count_comparison":
                education = match.group(1)
                work_year = match.group(2)
                return str(job_count_comparison(education, work_year))
            elif func_name == "skill_association":
                result = advisor.get_associated_skills(match.group(1))
                if not result:
                    return f"没有找到与'{match.group(1)}'相关的技术推荐。"
                else:
                    return f"根据关联规则分析，与'{match.group(1)}'相关的技术有: {', '.join(result)}"
            elif func_name == "position_skills":
                result = advisor.get_skills_by_position(match.group(1))
                if not result:
                    return f"没有找到'{match.group(1)}'岗位的技术要求信息。"
                else:
                    skill_info = [f"{skill} ({percentage})" for skill, percentage in result]
                    return f"从事{match.group(1)}岗位通常需要掌握以下技术（百分占比）: {', '.join(skill_info)}"
            elif func_name == "skill_positions":
                skills = match.group(1)
                result = advisor.get_positions_by_skills(skills)
                if result:
                    print("返回的数据结构：", result)  
                    relevant_positions = advisor.data[advisor.data['positionName'].isin([pos[0] for pos in result])]
                    columns_to_display = ['positionName', 'companyFullName', 'city', 'salary', 'workYear', 'education']
                    if all(col in relevant_positions.columns for col in columns_to_display):
                        rdata = relevant_positions[columns_to_display]
                        rdata = rdata.head(10)
                        st.dataframe(rdata)
                        position_info = [f"{pos[0]}（需求占比：{pos[1]}）" for pos in result]
                        response_text = f"根据数据集查询结果，您掌握 {skills} 技能，比较适合的岗位有：{', '.join(position_info)}。"
                        return response_text
                    else:
                        missing_columns = [col for col in columns_to_display if col not in relevant_positions.columns]
                        st.write(f"数据集中缺少以下列: {', '.join(missing_columns)}，请检查数据结构。")
                else:
                    st.write(f"没有找到需要'{skills}'技能的岗位。")
                    return f"没有找到需要'{skills}'技能的岗位。"
    return None

def complete_prompt(prompt, history):
    for message in reversed(history):
        if message["role"] == "user":
            education_match = re.search(r'(.*)学历', message["content"])
            if education_match and "工作年限" in message["content"]:
                education = education_match.group(1)
                work_year_match = re.search(r'\d+-\d+年', prompt)
                if work_year_match:
                    work_year = work_year_match.group(0)
                    new_prompt = f"{education}学历和{work_year}工作年限要求下，各职位的招聘数量对比如何？"
                    return new_prompt
    return prompt

def clear_chat_history():
    st.session_state.messages = [{"role": "assistant", "content": "你好我是职业规划助手，有什么可以帮助你的？"}]
    st.session_state.charts = []

# ==============================================
# 可视化分析部分 (来自app1.py)
# ==============================================

def update_chart():
    print("图表已更新")

def update_sidebar():
    with st.sidebar:
        st.markdown("""
        <style>
        .big-title {
            font-size: 24px !important;
            font-weight: bold !important;
        }
        </style>
        """, unsafe_allow_html=True)
        
        st.markdown('<p class="big-title">可视化分析</p>', unsafe_allow_html=True)
        
        tab_names = [
            "学历岗位需求",
            "薪资增长趋势",
            "语言岗位需求",
            "福利行业分布",
            "学历年限对比"
        ]
        st.session_state.selected_tab_index = st.selectbox(
            "选择问题", 
            range(len(tab_names)), 
            format_func=lambda x: tab_names[x], 
            key="question_selectbox"
        )
        
        st.title("过滤选项")
        i = st.session_state.selected_tab_index
        
        if i == 0:
            unique_educations = data['education'].unique().tolist()
            education_options = ["空"] + unique_educations
            education = st.selectbox(
                "选择学历要求",
                options=education_options,
                index=0,
                key="education_selectbox_sidebar"
            )
            unique_positions = data['positionName'].unique().tolist()
            selected_positions = st.multiselect(
                "选择岗位",
                options=unique_positions,
                default=[],
                key="position_multiselect_sidebar"
            )
            return education, selected_positions
        
        elif i == 1:
            def extract_salary(salary_str):
                try:
                    if isinstance(salary_str, str):
                        parts = salary_str.replace('k', '').split('-')
                        if len(parts) == 2:
                            return int(parts[0]), int(parts[1])
                        elif len(parts) == 1:
                            return int(parts[0]), int(parts[0])
                    elif isinstance(salary_str, (int, float)):
                        return salary_str, salary_str
                except ValueError:
                    return 0, 0

            salary_values = data['salary'].apply(lambda x: extract_salary(x))
            all_salary_values = [val for min_val, max_val in salary_values for val in [min_val, max_val]]
            valid_salary_values = [val for val in all_salary_values if val > 0]
            min_salary = max(0, min(valid_salary_values)) if valid_salary_values else 0
            max_salary = 65

            city = st.multiselect(
                "选择城市",
                options=data['city'].unique().tolist(),
                default=[],
                key="city_multiselect_tab1_sidebar"
            )
            salary_range = st.slider(
                "选择薪资范围（k）",
                min_value=min_salary,
                max_value=max_salary,
                value=(0, max_salary),
                step=5,
                key="salary_slider_tab1_sidebar"
            )
            return city, salary_range
        
        elif i == 2:
            programming_languages = ["Java", "Python", "C++", "JavaScript", "C#", "Go", "Ruby"]
            language_filter = st.multiselect(
                "选择编程语言",
                options=programming_languages,
                default=programming_languages,
                key="language_multiselect_tab2",
                on_change=update_chart
            )
            position_options = data['positionName'].unique().tolist()
            position_filter = st.selectbox(
                "选择岗位",
                options=[""] + position_options,
                index=0,
                key="position_selectbox_tab2",
                on_change=update_chart
            )
            if position_filter == "":
                position_filter = None
            return language_filter, position_filter
        
        elif i == 3:
            benefit_freq = data['companyLabelList'].str.extractall(r"'(.*?)'")[0].value_counts()
            top_ten_benefits = benefit_freq.head(10).index.tolist()
            
            benefits = st.multiselect(
                "选择福利",
                options=top_ten_benefits,
                default=[],
                key="benefits_multiselect",
                on_change=update_chart
            )
            industry_options = ["不限"] + data['industryField'].str.split(',').explode().unique().tolist()
            industry_filter = st.selectbox(
                "选择行业",
                options=industry_options,
                index=0,
                key="industry_selectbox",
                on_change=update_chart
            )
            return benefits, industry_filter
        
        elif i == 4:
            education_filter = st.selectbox(
                "选择学历要求",
                options=data['education'].unique().tolist() + ["不限"],
                index=0,
                key="education_selectbox_tab4",
                on_change=update_chart
            )
            work_year_range = st.slider(
                "选择工作年限范围",
                min_value=0,
                max_value=10,
                value=(0, 10),
                key="work_year_slider",
                on_change=update_chart
            )
            position = st.multiselect(
                "选择职位类型",
                options=data['positionName'].unique().tolist(),
                default=[],
                key="position_multiselect_tab4",
                on_change=update_chart
            )
            return education_filter, work_year_range, position

# ==============================================
# 主应用界面
# ==============================================

def main():
    # 设置页面配置
    st.set_page_config(
        page_title="PathFinder职途明灯",
        page_icon=":bar_chart:",
        layout="wide"
    )
    
    # 初始化认证系统
    initialize_auth()
    
    # 处理切换登录/注册的请求
    if st.session_state.get('switch_to_register'):
        st.session_state.auth_mode = 'register'
        st.session_state.switch_to_register = False
        st.experimental_rerun()
    
    if st.session_state.get('switch_to_login'):
        st.session_state.auth_mode = 'login'
        st.session_state.switch_to_login = False
        st.experimental_rerun()

    # 如果用户未登录，显示认证界面
    if not st.session_state.logged_in:
        show_auth_form()
        return
    
    # 用户已登录，显示主应用
    # 初始化session state
    if 'selected_tab' not in st.session_state:
        st.session_state.selected_tab = "可视化分析"
    if 'messages' not in st.session_state:
        st.session_state.messages = [{"role": "assistant", "content": "你好我是职业规划助手，有什么可以帮助你的？"}]
    if 'charts' not in st.session_state:
        st.session_state.charts = []
    if 'chart_counter' not in st.session_state:
        st.session_state.chart_counter = 0
    if 'selected_tab_index' not in st.session_state:
        st.session_state.selected_tab_index = 0

    # 设置API Token
    API_TOKEN = "0e333906a9ee486ebcf32b5d89f10b58.JYCfgpGQqYVkvDur"
    st.session_state['API_TOKEN'] = API_TOKEN

    # 顶部导航栏 - 显示用户信息和登出按钮
    st.markdown("""
    <style>
    .user-navbar {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 10px 20px;
        background-color: #f0f2f6;
        border-radius: 5px;
        margin-bottom: 20px;
    }
    .user-info {
        font-weight: bold;
        color: #2c3e50;
        margin: 0;
        padding: 8px 0;
    }
    </style>
    """, unsafe_allow_html=True)

    # 使用columns布局实现导航栏
    col1, col2 = st.columns([0.8, 0.2])
    with col1:
        st.markdown(f'<p class="user-info">欢迎, {st.session_state.current_user}</p>', unsafe_allow_html=True)
    with col2:
        if st.button("登出", key="logout_btn"):
            logout_user()
            st.rerun()
    
    if st.session_state.get('logout'):
        logout_user()
        st.rerun()

    # 侧边栏导航
    st.sidebar.title("导航菜单")
    app_mode = st.sidebar.radio(
        "选择功能模式",
        ["可视化分析", "智能聊天助手"],
        index=0 if st.session_state.selected_tab == "可视化分析" else 1
    )
    
    st.session_state.selected_tab = app_mode
    
    if app_mode == "可视化分析":
        show_visualization()
    else:
        show_chatbot()

def show_visualization():
    st.title("📊 招聘数据可视化分析")
    st.markdown("""
    <style>
    .big-font {
        font-size:18px !important;
    }
    </style>
    """, unsafe_allow_html=True)
    
    sidebar_result = update_sidebar()
    i = st.session_state.selected_tab_index
    
    if i == 0:
        st.header("不同岗位对不同学历层次学生的职位需求分布如何？")
        education, selected_positions = sidebar_result
        
        filtered_df = data.copy()
        if selected_positions:
            filtered_df = filtered_df[filtered_df['positionName'].isin(selected_positions)]
        if education != "空":
            if education in filtered_df['education'].unique():
                filtered_df = filtered_df[filtered_df['education'] == education]
        
        grouped_df = filtered_df.groupby(['positionName', 'education']).size().reset_index(name='职位数量')
        
        if not grouped_df.empty:
            fig = px.bar(grouped_df, x='positionName', y='职位数量', color='education', barmode='stack')
            st.plotly_chart(fig)
        else:
            st.warning("根据当前过滤条件，没有可用数据。请调整过滤条件。")
            
    elif i == 1:
        st.header("各城市不同工作年限要求下，职位的平均薪资增长趋势是怎样的？")
        city_filter, salary_range_filter = sidebar_result
        
        filtered_df = data.copy()
        if isinstance(city_filter, str):
            city_filter = [city_filter]
        if city_filter:
            filtered_df = filtered_df[filtered_df['city'].isin(city_filter)]
        
        filtered_df['avg_salary'] = filtered_df['salary'].apply(extract_salary_avg)
        
        if salary_range_filter:
            filtered_df = filtered_df[
                (filtered_df['avg_salary'] >= salary_range_filter[0]) & 
                (filtered_df['avg_salary'] <= salary_range_filter[1])
            ]
        
        work_year_order = ['在校/应届', '1年以下', '1-3年', '3-5年', '5-10年', '10年以上', '不限']
        filtered_df['workYear'] = pd.Categorical(filtered_df['workYear'], categories=work_year_order, ordered=True)
        
        grouped_df = filtered_df.groupby(['city', 'workYear'])['avg_salary'].mean().reset_index()
        grouped_df = grouped_df.sort_values(by='workYear')
        
        if not grouped_df.empty:
            fig = px.line(grouped_df, x='workYear', y='avg_salary', color='city', markers=True)
            fig.update_layout(
                xaxis_title='工作年限',
                yaxis_title='平均薪资（k）'
            )
            st.plotly_chart(fig)
        else:
            st.warning("根据当前过滤条件，没有可用数据。请调整过滤条件。")
            
    elif i == 2:
        st.header("不同编程语言在不同岗位的需求占比如何？")
        language_filter, position_filter = sidebar_result
        
        filtered_df = data.copy()
        if position_filter:
            position_filter = [position_filter]
            filtered_df = filtered_df[filtered_df['positionName'].isin(position_filter)]
        
        def extract_languages(requirement):
            requirement_str = str(requirement)
            return [lang for lang in language_filter if lang in requirement_str]
        
        filtered_df['languages'] = filtered_df['positionDetail'].apply(extract_languages)
        exploded_df = filtered_df.explode('languages')
        language_counts = exploded_df['languages'].value_counts().reset_index(name='需求数量')
        
        if not language_counts.empty:
            fig = px.pie(language_counts, values='需求数量', names='languages', title='不同编程语言在所选岗位的需求占比')
            st.plotly_chart(fig)
        else:
            st.warning("根据当前过滤条件，没有可用数据。请调整过滤条件。")
            
    elif i == 3:
        st.header("具有特定福利的公司，在不同行业的分布情况如何？")
        benefits, industry_filter = sidebar_result
        
        filtered_df = data.copy()
        if benefits:
            def has_all_benefits(labels):
                labels_str = str(labels)
                return all(benefit in labels_str for benefit in benefits)
            
            filtered_df = filtered_df[filtered_df['companyLabelList'].apply(has_all_benefits)]
        
        if industry_filter and industry_filter != "不限":
            filtered_df['industryField'] = filtered_df['industryField'].fillna('')
            filtered_df = filtered_df[filtered_df['industryField'].str.contains(industry_filter)]
        
        industry_counts = filtered_df.groupby('industryField').size().reset_index(name='公司数量')
        
        if not industry_counts.empty:
            fig_bar = px.bar(industry_counts, x='industryField', y='公司数量',
                             title='不同行业具有特定福利的公司数量分布')
            st.plotly_chart(fig_bar)
        else:
            st.warning("根据当前过滤条件，没有可用数据。请调整过滤条件。")
            
    elif i == 4:
        st.header("不同学历和工作年限要求下，各职位的招聘数量对比如何？")
        education_filter, work_year_range, position = sidebar_result
        
        filtered_df = data.copy()
        if position:
            filtered_df = filtered_df[filtered_df['positionName'].isin(position)]
        if education_filter != "不限":
            filtered_df = filtered_df[filtered_df['education'] == education_filter]
        
        work_year_mapping = {
            '在校/应届': 0,
            '1年以下': 1,
            '1-3年': 2,
            '3-5年': 4,
            '5-10年': 7,
            '10年以上': 11,
            '不限': 0
        }
        filtered_df['workYear_num'] = filtered_df['workYear'].map(work_year_mapping)
        filtered_df = filtered_df[
            (filtered_df['workYear_num'] >= work_year_range[0]) & 
            (filtered_df['workYear_num'] <= work_year_range[1])
        ]
        
        grouped_df = filtered_df.groupby(['positionName', 'education', 'workYear']).size().reset_index(name='招聘数量')
        
        if not grouped_df.empty:
            fig = px.bar(grouped_df, x='positionName', y='招聘数量', color='education', barmode='group',
                         facet_col='workYear', facet_col_wrap=3)
            fig.update_layout(
                xaxis_title='职位',
                yaxis_title='招聘数量',
                title='不同学历和工作年限要求下各职位的招聘数量对比'
            )
            st.plotly_chart(fig)
        else:
            st.warning("根据当前过滤条件，没有可用数据。请调整过滤条件。")

def show_chatbot():
    st.title("💬 职业规划智能助手")
    st.markdown("""
    <style>
    .chat-message {
        padding: 1rem;
        border-radius: 0.5rem;
        margin-bottom: 1rem;
    }
    .user-message {
        background-color: #f0f2f6;
    }
    .assistant-message {
        background-color: #e6f7ff;
    }
    </style>
    """, unsafe_allow_html=True)
    
    # 聊天机器人设置
    with st.sidebar:
        st.title('聊天设置')
        model = st.selectbox("选择模型", ["glm-3-turbo", "glm-4"])
        max_tokens = st.slider("最大响应长度", 0, 2000, value=512)
        temperature = st.slider("创造性", 0.0, 2.0, value=0.8)
        st.button('清空聊天记录', on_click=clear_chat_history)
 

    # 在侧边栏添加问题示例
    st.sidebar.markdown("### 你可以这么问我：")
    st.sidebar.markdown("1. 算法工程师对不同学历层次学生的职位需求分布如何")
    st.sidebar.markdown("2. 北京不同工作年限要求下，职位的平均薪资增长趋势是怎样的？")
    st.sidebar.markdown("3. Python在数据分析岗位的需求占比如何")
    st.sidebar.markdown("4. 提供五险一金福利的公司，在金融行业和上海的分布情况如何？")
    st.sidebar.markdown("5. 本科学历和1-3年工作年限要求下，各职位的招聘数量对比如何？")
    st.sidebar.markdown("6. 我比较擅长java，请给我推荐一些关联技术")
    st.sidebar.markdown("7. 从事算法工程师岗位需要学什么？")
    st.sidebar.markdown("8. 我会mysql，什么岗位比较适合我？")


    # 显示聊天历史
    for message in st.session_state.messages:
        with st.chat_message(message["role"]):
            st.write(message["content"])
            if "chart" in message and message["chart"] is not None:
                st.plotly_chart(message["chart"], key=f"chart_{st.session_state.chart_counter}")
                st.session_state.chart_counter += 1
    
    # 用户输入处理
    if prompt := st.chat_input("请输入您的问题..."):
        original_prompt = prompt
        prompt = complete_prompt(prompt, st.session_state.messages)
        
        st.session_state.messages.append({"role": "user", "content": original_prompt})
        with st.chat_message("user"):
            st.markdown(original_prompt)
        
        with st.chat_message("assistant"):
            with st.spinner("思考中..."):
                local_response = search_local_data(prompt)
                chart = None
                
                if local_response is not None:
                    llm_prompt = f"问题: {prompt}，根据查询结果显示，{local_response}，请基于此结果进行分析回复。"
                    llm_response = ask_glm(
                        st.session_state['API_TOKEN'], model, max_tokens, temperature,
                        [{"role": "user", "content": llm_prompt}]
                    )['choices'][0]['message']['content']
                    full_response = llm_response
                    st.markdown(full_response)
                    
                    # 图表生成逻辑
                    match = None
                    for func_name, pattern in patterns.items():
                        match = re.search(pattern, prompt)
                        if match:
                            break
                    
                    if match:
                        if func_name not in ["count_job", "average_salary", "count_job_by_city"]:
                            if func_name == "job_distribution_by_education":
                                job_name = match.group(1)
                                result = job_distribution_by_education(job_name)
                                df = pd.DataFrame({
                                    '学历': result.index,
                                    '职位数量': result.values
                                })
                                chart = px.bar(df, x='学历', y='职位数量', title=f'{job_name} 对不同学历层次学生的职位需求分布')
                            elif func_name == "salary_trend_by_experience":
                                city = match.group(1)
                                result = salary_trend_by_experience(city)
                                df = pd.DataFrame({
                                    '工作年限': result.index,
                                    '平均薪资': result.values
                                })
                                df['工作年限_order'] = df['工作年限'].map({
                                    '在校/应届': 0,
                                    '1年以下': 1,
                                    '1-3年': 2,
                                    '3-5年': 3,
                                    '5-10年': 4,
                                    '10年以上': 5,
                                    '不限': 6
                                })
                                df = df.sort_values(by='工作年限_order')
                                df = df.drop('工作年限_order', axis=1)
                                chart = px.line(df, x='工作年限', y='平均薪资', markers=True, title=f'{city} 不同工作年限要求下职位的平均薪资增长趋势')
                            elif func_name == "language_demand_ratio":
                                job_name = match.group(2)
                                result = language_demand_ratio(job_name)
                                df = pd.DataFrame({
                                    '编程语言': result.index,
                                    '需求占比': result.values
                                })
                                chart = px.pie(df, values='需求占比', names='编程语言', title=f'{job_name} 不同编程语言的需求占比')
                            elif func_name == "company_distribution_by_benefit":
                                benefit = match.group(1)
                                result = company_distribution_by_benefit(benefit)
                                df = result.reset_index(name='公司数量')
                                chart = px.bar(df, x='industryField', y='公司数量', color='city', title=f'提供 {benefit} 福利的公司在不同行业和城市的分布')
                            elif func_name == "job_count_comparison":
                                education = match.group(1)
                                work_year = match.group(2)
                                result = job_count_comparison(education, work_year)
                                df = pd.DataFrame({
                                    '岗位名称': result.index,
                                    '招聘数量': result.values
                                })
                                chart = px.bar(df, x='岗位名称', y='招聘数量', title=f'{education} 学历和 {work_year} 工作年限要求下各职位的招聘数量对比')
                            elif func_name == "skill_association":
                                target_skill = match.group(1)
                                result = advisor.get_associated_skills(target_skill)
                                if result:
                                    df = pd.DataFrame({
                                        '关联技术': result,
                                        '数量': [1] * len(result)
                                    })
                                    chart = px.pie(df, values='数量', names='关联技术', title=f'与 {target_skill} 相关的关联技术', hole=0.3)
                                    chart.update_traces(textinfo='label', hoverinfo='label')
                            elif func_name == "position_skills":
                                position = match.group(1)
                                result = advisor.get_skills_by_position(position)
                                if result:
                                    skills, percentages = zip(*result)
                                    df = pd.DataFrame({
                                        '技术': skills,
                                        '百分占比': [float(percentage.strip('%')) for percentage in percentages]
                                    })
                                    chart = px.bar(df, x='技术', y='百分占比', title=f'{position} 岗位需要的技术及百分占比')
                            elif func_name == "skill_positions":
                                skills = match.group(1)
                                result = advisor.get_positions_by_skills(skills)
                                if result:
                                    positions, percentages = zip(*result)
                                    df = pd.DataFrame({
                                        '岗位名称': positions,
                                        '百分占比': [float(percentage.strip('%')) for percentage in percentages]
                                    })
                                    st.dataframe(df[['岗位名称', '百分占比']])

                            if chart is not None:
                                st.plotly_chart(chart, key=f"chart_{st.session_state.chart_counter}")
                                st.session_state.chart_counter += 1
                                st.session_state.charts.append(chart)

                else:
                    full_response = ask_glm(
                        st.session_state['API_TOKEN'], model, max_tokens, temperature,
                        [{"role": "user", "content": prompt}]
                    )['choices'][0]['message']['content']
                    st.markdown(full_response)
                
                message = {"role": "assistant", "content": full_response, "chart": chart}
                st.session_state.messages.append(message)

if __name__ == "__main__":
    main()